1 using System;
2 using UnityEngine;
3
4 namespace UnityStandardAssets.Cameras
5 {
6 public class LookatTarget : AbstractTargetFollower
7 {
8 // A simple script to make one object look at another,
9 // but with optional constraints which operate relative to
10 // this gameobject's initial rotation.
11
12 // Only rotates around local X and Y.
13
14 // Works in local coordinates, so if this object is parented
15 // to another moving gameobject, its local constraints will
16 // operate correctly
17 // (Think: looking out the side window of a car, or a gun turret
18 // on a moving spaceship with a limited angular range)
19
20 // to have no constraints on an axis, set the rotationRange greater than 360.
21
22 [SerializeField] private Vector2 m_RotationRange;
23 [SerializeField] private float m_FollowSpeed = 1;
24
25 private Vector3 m_FollowAngles;
26 private Quaternion m_OriginalRotation;
27
28 protected Vector3 m_FollowVelocity;
29
30
31 // Use this for initialization
32 protected override void Start()
33 {
34 base.Start();
35 m_OriginalRotation = transform.localRotation;
36 }
37
38
39 protected override void FollowTarget(float deltaTime)
40 {
41 // we make initial calculations from the original local rotation
42 transform.localRotation = m_OriginalRotation;
43
44 // tackle rotation around Y first
45 Vector3 localTarget = transform.InverseTransformPoint(m_Target.position);
46 float yAngle = Mathf.Atan2(localTarget.x, localTarget.z)*Mathf.Rad2Deg;
47
48 yAngle = Mathf.Clamp(yAngle, -m_RotationRange.y*0.5f, m_RotationRange.y*0.5f);
49 transform.localRotation = m_OriginalRotation*Quaternion.Euler(0, yAngle, 0);
50
51 // then recalculate new local target position for rotation around X
52 localTarget = transform.InverseTransformPoint(m_Target.position);
53 float xAngle = Mathf.Atan2(localTarget.y, localTarget.z)*Mathf.Rad2Deg;
54 xAngle = Mathf.Clamp(xAngle, -m_RotationRange.x*0.5f, m_RotationRange.x*0.5f);
55 var targetAngles = new Vector3(m_FollowAngles.x + Mathf.DeltaAngle(m_FollowAngles.x, xAngle),
56 m_FollowAngles.y + Mathf.DeltaAngle(m_FollowAngles.y, yAngle));
57
58 // smoothly interpolate the current angles to the target angles
59 m_FollowAngles = Vector3.SmoothDamp(m_FollowAngles, targetAngles, ref m_FollowVelocity, m_FollowSpeed);
60
61
62 // and update the gameobject itself
63 transform.localRotation = m_OriginalRotation*Quaternion.Euler(-m_FollowAngles.x, m_FollowAngles.y, 0);
64 }
65 }
66 }